﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Revit;
using YJKArch.AreaStatistical.DataManager;
using YJKArch.AreaStatistical.Filter;
using YJKArch.ModifiedArea;
using YJKArch.Utils;

namespace YJKArch.AreaStatistical.SearchLoop
{
	public class AreaInfoCreator
	{
		public AreaInfoCreator(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
		}

		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		public void CreateSuite()
		{
			try
			{
				this.ShowLabeledSuiteInfo();
				this.CreateSuiteAreaByRoom();
			}
			catch (Exception)
			{
				this.HideLabeledSuiteInfo();
			}
			this.HideLabeledSuiteInfo();
		}

		public Result CreateFillAreaByRoom(ref string message)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			List<ElementId> list = this.FilterAreaAndBoundarys(document);
			OffsetWallLine offsetWallLine = new OffsetWallLine(this.m_Revit, "OutLine");
			if (list.Count > 0)
			{
				DialogResult dialogResult = MessageBox.Show("当前视图已存在面积对象，是否删除？", "盈建科提示", MessageBoxButtons.YesNoCancel);
				if (DialogResult.Cancel == dialogResult)
				{
					return Autodesk.Revit.UI.Result.Cancelled;
				}
				if (DialogResult.Yes == dialogResult)
				{
					this.DeleteAreaAndBoundarys(document, list);
				}
			}
			List<Wall> outWallsCurViewPlan = offsetWallLine.GetOutWallsCurViewPlan(document.ActiveView as Autodesk.Revit.DB.ViewPlan, document);
			SetAreaInfoForm setAreaInfoForm = new SetAreaInfoForm(SetAreaInfoForm.FormType.FT_FillArea);
			setAreaInfoForm.Show(AreaInfoCreator._hWndRevit);
			int wMsg = 7;
			AreaInfoCreator.SendMessage(AreaInfoCreator._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			try
			{
				List<Room> rooms = new List<Room>();
				while (this.GetRooms(ref rooms))
				{
					List<ElementId> roomIdList = new List<ElementId>();
					List<Area> areaList = new List<Area>();
					if (!this.SearchFillAreaByRoom(rooms, setAreaInfoForm.IncludeColumn, setAreaInfoForm.m_SelectRangeType, outWallsCurViewPlan, ref roomIdList, ref areaList, ref message))
					{
						if (message.CompareTo("") != 0)
						{
							MessageBox.Show(message, "盈建科提示");
						}
					}
					else
					{
						this.CreateFillAreaByRoom(areaList, roomIdList, setAreaInfoForm.AreaName);
					}
				}
			}
			catch (Exception ex)
			{
				message = ex.Message;
				setAreaInfoForm.Close();
				return Autodesk.Revit.UI.Result.Failed;
			}
			setAreaInfoForm.Close();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private List<ElementId> FilterAreaAndBoundarys(Autodesk.Revit.DB.Document doc)
		{
			List<ElementId> list = new List<ElementId>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, doc.ActiveView.Id);
			filteredElementCollector.OfClass(typeof(SpatialElement));
			foreach (Element element in filteredElementCollector)
			{
				Area area = element as Area;
				if (area != null)
				{
					list.Add(area.Id);
				}
			}
			FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(doc, doc.ActiveView.Id);
			filteredElementCollector2.OfCategory(BuiltInCategory.OST_AreaSchemeLines).OfClass(typeof(CurveElement));
			foreach (Element element2 in filteredElementCollector2)
			{
				ModelCurve modelCurve = element2 as ModelCurve;
				if (modelCurve != null)
				{
					list.Add(modelCurve.Id);
				}
			}
			return list;
		}

		private void DeleteAreaAndBoundarys(Autodesk.Revit.DB.Document doc, List<ElementId> areaAndBoundarys)
		{
			Transaction transaction = new Transaction(doc, "Delete Areas");
			transaction.Start();
			doc.Delete(areaAndBoundarys);
			transaction.Commit();
		}

		private bool SearchFillAreaByRoom(List<Room> rooms, bool includeColumn, string RangeType, List<Wall> lstOutWall, ref List<ElementId> roomIdList, ref List<Area> areaList, ref string message)
		{
			AreaLoopSearcher areaLoopSearcher = new AreaLoopSearcher(this.m_Revit);
			areaList.Clear();
			if (includeColumn)
			{
				if (!areaLoopSearcher.SearchFillAreaLoops_IncludColumn(rooms, false, false, RangeType, lstOutWall, ref areaList, ref roomIdList, ref message))
				{
					return false;
				}
			}
			else if (!areaLoopSearcher.SearchAreaLoops(rooms, EdgePosition.EP_Center, false, false, RangeType, lstOutWall, ref areaList, ref roomIdList, ref message))
			{
				return false;
			}
			return true;
		}

		private void CreateFillAreaByRoom(List<Area> areaList, List<ElementId> roomIdList, string areaName)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document);
			transaction.Start("set area info");
			foreach (Area area in areaList)
			{
				try
				{
					area.get_Parameter(BuiltInParameter.ROOM_NAME).Set(areaName);
					AreaInfoManager.WriteExtensibleStorageToArea(area, AreaType.AT_Fill, areaName, "", roomIdList);
				}
				catch (Exception)
				{
				}
			}
			List<ElementId> list = this.FilterAreaAndBoundarys(document);
			if (list.Count > 0)
			{
				ElementTransformUtils.MoveElements(document, list, XYZ.BasisX * AssistFunc.mmToFeet(1.0));
				ElementTransformUtils.MoveElements(document, list, XYZ.BasisX * AssistFunc.mmToFeet(-1.0));
			}
			transaction.Commit();
		}

		private bool CreateSuiteAreaByRoom()
		{
			SetAreaInfoForm setAreaInfoForm = new SetAreaInfoForm(SetAreaInfoForm.FormType.FT_SuiteArea);
			setAreaInfoForm.Show(AreaInfoCreator._hWndRevit);
			int wMsg = 7;
			AreaInfoCreator.SendMessage(AreaInfoCreator._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			try
			{
				List<Area> areaList = new List<Area>();
				List<ElementId> roomIdList = new List<ElementId>();
				while (this.SearchSuiteAreaByRoom(ref areaList, ref roomIdList))
				{
					this.CreateSuiteAreaByRoom(areaList, roomIdList, setAreaInfoForm.AreaName, setAreaInfoForm.HoomNumb);
					try
					{
						int num = Convert.ToInt32(setAreaInfoForm.HoomNumb);
						setAreaInfoForm.HoomNumb = (num + 1).ToString();
					}
					catch (Exception)
					{
					}
				}
			}
			catch (Exception)
			{
				setAreaInfoForm.Close();
				return false;
			}
			setAreaInfoForm.Close();
			return true;
		}

		private bool GetRooms(ref List<Room> rooms)
		{
			IList<Reference> list = null;
			rooms.Clear();
			Selection selection = this.m_Revit.Application.ActiveUIDocument.Selection;
			try
			{
				list = selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new RoomsFilter(), "请框选房间生成建筑面积");
			}
			catch (Exception)
			{
				return false;
			}
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			foreach (Reference reference in list)
			{
				Room room = document.GetElement(reference) as Room;
				if (room != null)
				{
					rooms.Add(room);
				}
			}
			return true;
		}

		private bool SearchSuiteAreaByRoom(ref List<Area> areaList, ref List<ElementId> roomIdList)
		{
			List<Room> rooms = new List<Room>();
			if (!this.GetRooms(ref rooms))
			{
				return false;
			}
			AreaLoopSearcher areaLoopSearcher = new AreaLoopSearcher(this.m_Revit);
			areaList.Clear();
			roomIdList.Clear();
			string text = "";
			if (!areaLoopSearcher.SearchAreaLoops(rooms, EdgePosition.EP_Center, false, true, null, null, ref areaList, ref roomIdList, ref text))
			{
				MessageBox.Show("未发现房间边界，请先设置房间", "盈建科提示");
				return false;
			}
			return true;
		}

		private void CreateSuiteAreaByRoom(List<Area> areaList, List<ElementId> roomIdList, string areaName, string hoomNumb)
		{
			Transaction transaction = new Transaction(this.m_Revit.Application.ActiveUIDocument.Document);
			transaction.Start("set area info");
			foreach (Area area in areaList)
			{
				try
				{
					area.get_Parameter(BuiltInParameter.ROOM_NAME).Set(areaName);
					area.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).Set("户号：" + hoomNumb);
					AreaInfoManager.WriteExtensibleStorageToArea(area, AreaType.AT_Suite, areaName, hoomNumb, roomIdList);
					this.ShowSingleLabeledSuiteInfo(area);
				}
				catch (Exception)
				{
				}
			}
			transaction.Commit();
		}

		private List<string> GetAllHoomNumbList()
		{
			List<string> list = new List<string>();
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			ElementId id = this.m_Revit.Application.ActiveUIDocument.ActiveView.Id;
			foreach (Element element in new FilteredElementCollector(document, id).OfCategory(BuiltInCategory.OST_Areas))
			{
				Area area = element as Area;
				if (area != null)
				{
					AreaType areaType = AreaType.AT_None;
					if (AreaInfoManager.HaxExtensibleStorageInArea(area, ref areaType))
					{
						string text = "";
						string item = "";
						List<ElementId> list2 = new List<ElementId>();
						AreaInfoManager.ReadExtensibleStorageFromArea(area, ref areaType, ref text, ref item, ref list2);
						list.Add(item);
					}
				}
			}
			return list;
		}

		private bool HasDuplicateNumbers(string hoomNumb)
		{
			return this.GetAllHoomNumbList().FindIndex((string value) => value.CompareTo(hoomNumb) == 0) != -1;
		}

		private void ShowLabeledSuiteInfo()
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document);
			transaction.Start("show label");
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			foreach (Area area in this.GetAreas(document, activeView.Id))
			{
				string text = area.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).AsString();
				if (text.CompareTo("") != 0)
				{
					string info = text;
					XYZ xyz = (area.Location as LocationPoint).Point;
					xyz -= XYZ.BasisY * Common.MMToFeet(10.0);
					ElementId value = this.NewLabeledText(info, xyz);
					KeyValuePair<ElementId, ElementId> item = new KeyValuePair<ElementId, ElementId>(area.Id, value);
					this.m_Suite2ndTempTextList.Add(item);
				}
			}
			transaction.Commit();
		}

		private List<Area> GetAreas(Autodesk.Revit.DB.Document doc, ElementId viewId)
		{
			List<Area> list = new List<Area>();
			foreach (Element element in new FilteredElementCollector(doc, viewId).OfCategory(BuiltInCategory.OST_Areas))
			{
				Area area = element as Area;
				if (area != null)
				{
					AreaType areaType = AreaType.AT_None;
					if (AreaInfoManager.HaxExtensibleStorageInArea(area, ref areaType) && areaType == AreaType.AT_Suite)
					{
						list.Add(area);
					}
				}
			}
			return list;
		}

		private void ShowSingleLabeledSuiteInfo(Area area)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			int num = this.m_Suite2ndTempTextList.FindIndex((KeyValuePair<ElementId, ElementId> value) => value.Key.IntegerValue == area.Id.IntegerValue);
			string text = area.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).AsString();
			if (text.CompareTo("") != 0)
			{
				string info = text;
				XYZ xyz = (area.Location as LocationPoint).Point;
				xyz -= XYZ.BasisY * Common.MMToFeet(10.0);
				ElementId value3 = this.NewLabeledText(info, xyz);
				if (num != -1)
				{
					ElementId value2 = this.m_Suite2ndTempTextList[num].Value;
					this.DeleteLable(value2);
					this.m_Suite2ndTempTextList[num] = new KeyValuePair<ElementId, ElementId>(area.Id, value3);
					return;
				}
				KeyValuePair<ElementId, ElementId> item = new KeyValuePair<ElementId, ElementId>(area.Id, value3);
				this.m_Suite2ndTempTextList.Add(item);
			}
		}

		private void HideLabeledSuiteInfo()
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document);
			transaction.Start("hide label");
			foreach (KeyValuePair<ElementId, ElementId> keyValuePair in this.m_Suite2ndTempTextList)
			{
				try
				{
					document.Delete(keyValuePair.Value);
				}
				catch (Exception)
				{
				}
			}
			transaction.Commit();
		}

		private void DeleteLable(ElementId lableId)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document);
			transaction.Start("hide label");
			try
			{
				document.Delete(lableId);
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
			transaction.Commit();
		}

		private ElementId NewLabeledText(string info, XYZ pos)
		{
			Autodesk.Revit.DB.Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			XYZ basisX = XYZ.BasisX;
			XYZ basisY = XYZ.BasisY;
            TextAlignFlags textAlign = (TextAlignFlags)640;
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			TextNote textNode = document.GetTextNode(activeView, pos, basisX, basisY, 1.0, textAlign, info);
			TextNoteType labelTextNoteType = this.GetLabelTextNoteType();
			if (labelTextNoteType != null)
			{
				textNode.TextNoteType = labelTextNoteType;
			}
			return textNode.Id;
		}

		private TextNoteType GetLabelTextNoteType()
		{
			string strB = "宋体 3mm";
			string text = "HY_SuiteInfoLabel";
			int num = 255;
			TextNoteType textNoteType = null;
			TextNoteType textNoteType2 = null;
			TextNoteType textNoteType3 = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Revit.Application.ActiveUIDocument.Document);
			filteredElementCollector.OfClass(typeof(TextNoteType));
			FilteredElementIterator elementIterator = filteredElementCollector.GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				TextNoteType textNoteType4 = element as TextNoteType;
				if (textNoteType4 != null)
				{
					if (textNoteType4.Name.CompareTo(text) == 0)
					{
						textNoteType = textNoteType4;
						break;
					}
					if (textNoteType2 == null && textNoteType4.Name.CompareTo(strB) == 0)
					{
						textNoteType2 = textNoteType4;
					}
					textNoteType3 = textNoteType4;
				}
			}
			if (textNoteType == null)
			{
				if (textNoteType3 == null)
				{
					return null;
				}
				if (textNoteType2 == null)
				{
					textNoteType2 = textNoteType3;
				}
				textNoteType = (textNoteType2.Duplicate(text) as TextNoteType);
				double num2 = Common.MMToFeet(3.5);
				textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).Set(num2);
				string text2 = "FangSong_GB2312";
				textNoteType.get_Parameter(BuiltInParameter.TEXT_FONT).Set(text2);
				double num3 = 0.7;
				textNoteType.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).Set(num3);
				double num4 = Common.MMToFeet(8.0);
				textNoteType.get_Parameter(BuiltInParameter.TEXT_TAB_SIZE).Set(num4);
				textNoteType.get_Parameter(BuiltInParameter.LINE_COLOR).Set(num);
			}
			return textNoteType;
		}

		public static WindowHandle _hWndRevit;

		private ExternalCommandData m_Revit;

		private List<KeyValuePair<ElementId, ElementId>> m_Suite2ndTempTextList = new List<KeyValuePair<ElementId, ElementId>>();
	}
}
